Skip to content

GDB 生成 coredump:抓取运行中进程的内存快照 ​

线上进程出了问题但没崩溃——内存缓慢增长、状态诡异地卡住、某个线程疑似死锁——这时候最想要的是一份「当时的完整现场」,又不能 kill 进程等它吐 core。GDB 的 generate-core-file 命令可以在 attach 到运行中进程后直接生成 coredump 文件,效果等同于进程崩溃时系统自动落盘的 core,之后完全可以离线慢慢分析。本文给出三种生成方式和一个容易踩的参数陷阱。

方法一:GDB 交互模式 ​

bash
# attach 到目标进程
gdb -p <PID>

# 生成 coredump(可指定文件名)
(gdb) generate-core-file /tmp/core.myapp
# 不指定文件名则默认 core.<PID>

# 生成完毕后 detach 退出
(gdb) detach
(gdb) quit

适合需要先观察一下进程状态(线程栈、变量)再决定是否快照的场景。

方法二:一行命令(非交互) ​

bash
gdb -p <PID> -batch -ex "generate-core-file /tmp/core.myapp" -ex "detach"

-batch 配合 -ex 不进交互界面,适合脚本化批量操作。

方法三:gcore ​

bash
# 直接在 shell 中生成,无需手动进入 GDB attach
gcore -o /tmp/core.myapp <PID>
# 注意:-o 指定的是文件名前缀,实际生成 /tmp/core.myapp.<PID>

gcore 本质上是 GDB 的封装(内部同样会 ptrace attach 暂停目标进程),效果相同,使用最简洁。日常排查推荐它。

陷阱就在 -o 参数:它接受的是文件名前缀而不是完整文件名,gcore 会自动追加 .PID 后缀(依据 man gcore)。指望拿到 /tmp/core.myapp 的脚本,实际拿到的是 /tmp/core.myapp.12345,路径拼错就会以为生成失败。想精确控制完整文件名,用方法一或方法二。

注意事项 ​

  • 进程暂停:生成 coredump 期间进程会被暂停(STOP),进程越大耗时越长,生产环境慎用;
  • 磁盘空间:coredump 文件大小约等于进程的 RSS,落盘前确认目标路径空间充足;
  • 权限:需要对目标进程有 ptrace 权限(同用户或 root),受 Yama ptrace_scope 限制的环境需先放开;
  • 进程恢复:生成完成后进程自动恢复运行,不受影响;
  • ulimit:generate-core-file 和 gcore 不受 ulimit -c 限制——它们由 GDB 直接写文件,不走内核的 core dump 管道。

离线分析 ​

拿到 coredump 后与二进制一起打开:

bash
gdb /path/to/binary /tmp/core.myapp

# 常用分析命令
(gdb) bt                  # 查看调用栈
(gdb) info threads        # 查看所有线程
(gdb) thread apply all bt # 所有线程调用栈

如果发布包里的二进制是 stripped 的,堆栈里只有地址没有函数名,需要配合调试符号包——可以参考《GDB attach 加载带调试信息的共享库符号》里的符号加载方法。

三种方式对比 ​

方法 优点 缺点
GDB 交互 可在生成前先检查进程状态 需要手动操作
GDB -batch 可脚本化,一行搞定 无法先检查
gcore 最简洁 -o 是前缀不是文件名,功能单一

要点 ​

  • 未崩溃的进程也能拿「完整现场」:attach 后 generate-core-file 或直接 gcore
  • gcore -o 是前缀语义,产物会带 .PID 后缀,脚本里别拼错路径
  • 快照期间进程暂停,大进程在生产环境要评估停顿代价
  • 产物不受 ulimit -c 影响,但需要 ptrace 权限和约等于 RSS 的磁盘空间
最近更新

基于 VitePress 构建